package com.yituo.mjworld.core.web.core;

import com.alibaba.fastjson.JSONObject;
import com.yituo.mjworld.core.utils.JwtTool;
import com.yituo.mjworld.mvc.entity.UserData;
import com.yituo.mjworld.mvc.entity.web.WebUser;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.UnsupportedEncodingException;

/**
 * 业务Http请求对象
 *
 * @author xq
 */
public class MyHttpRequest extends HttpServletRequestWrapper {
  private static final String CHECK_TOKEN = "checkToken";
  private static final String SPECIAL = "special";
  private static final int URL_PARAM_LENGTH = 3;
  /**
   * 表单
   */
  private BaseForm form;
  /**
   * 所属的Servlet 名称
   */
  private String servletName;
  /**
   * 所属的方法名称
   */
  private String methodName;
  /**
   * 所属的actionName
   */
  private String actionName;
  /**
   * 当前请求所属于的用户
   */
  private WebUser currentUser;
  /**
   * 响应状态,默认为200
   */
  private int status = MyHttpResponse.RES_STATUS_200_SUCCESS;
  /**
   * 错误信息
   */
  private String errorMsg;

  public MyHttpRequest(HttpServletRequest request) throws UnsupportedEncodingException {
    super(request);
    this.setCharacterEncoding("UTF-8");
    // 验证URL是否符合规范
    validateUrl();
    // 验证token并且抽取相关的用户
    validateToken();
  }

  /**
   * 验证方法token.
   * 访问的方法不免token,则解析并校验token.并获取到当前用户
   *
   * @return 校验通过返回真, 校验失败返回假
   */
  private boolean validateToken() {
    String token = this.getHeader("token");
    if (StringUtils.isEmpty(token)) {
      // 无token 情况下,设置当前用户为匿名用户,直接放行
      this.setCurrentUser(null);
      return true;
    }
    // 有Token 情况下,对token进行解析并获取到相应的用户
    JSONObject validateResult = JwtTool.validateToken(token);
    boolean auth = validateResult.getBoolean("auth");
    if (!auth) {
      // token校验不通过,直接拒绝访问资源
      this.setStatus(MyHttpResponse.RES_STATUS_401_TOKEN_ERROR);
      this.setErrorMsg(validateResult.getString("msg"));
      return false;
    } else {
      // token 符合规范,获取到相关用户
      String userId = validateResult.getJSONObject("payload").getString("userId");
      WebUser user = UserData.getUser(userId);
      if (user != null) {
        this.setCurrentUser(user);
      } else {
        this.setStatus(MyHttpResponse.RES_STATUS_401_TOKEN_ERROR);
        this.setErrorMsg("当前用户不存在!");
        // TODO:说明有不存在的UID,但是算法负责本站算法.需要联系管理员修改密钥.
        return false;
      }
      return true;
    }
  }

  /**
   * 验证URL.
   *
   * @return url 有效返回真,url 无效返回假
   */
  private boolean validateUrl() {
    String url = this.getRequestURL().toString();
    url = url.split("\\?")[0];
    String[] urlArr = url.split("/");
    if (urlArr.length < URL_PARAM_LENGTH) {
      // 请求参数不全
      this.errorMsg = "url数组长度小于3";
      this.status = MyHttpResponse.RES_STATUS_500_URL_ERROR;
      return false;
    }
    this.methodName = urlArr[urlArr.length - 1];
    this.actionName = urlArr[urlArr.length - 2];
    this.servletName = urlArr[urlArr.length - 3];
    if (StringUtils.isEmpty(this.methodName) || StringUtils.isEmpty(actionName) || StringUtils.isEmpty(servletName)) {
      this.errorMsg = "url不全!";
      this.status = MyHttpResponse.RES_STATUS_500_URL_ERROR;
      return false;
    }
    return true;
  }

  public String getServletName() {
    return servletName;
  }

  public void setServletName(String servletName) {
    this.servletName = servletName;
  }

  public String getMethodName() {
    return methodName;
  }

  public void setMethodName(String methodName) {
    this.methodName = methodName;
  }

  public String getActionName() {
    return actionName;
  }

  public void setActionName(String actionName) {
    this.actionName = actionName;
  }

  public WebUser getCurrentUser() {
    return currentUser;
  }

  public void setCurrentUser(WebUser currentUser) {
    this.currentUser = currentUser;
  }

  public int getStatus() {
    return status;
  }

  public void setStatus(int status) {
    this.status = status;
  }

  public String getErrorMsg() {
    return errorMsg;
  }

  public void setErrorMsg(String errorMsg) {
    this.errorMsg = errorMsg;
  }

  public BaseForm getForm() {
    return form;
  }

  public void setForm(BaseForm form) {
    this.form = form;
  }
}
